home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / tex / dvi / dvipssrc.zoo / afm2tfm.c next >
C/C++ Source or Header  |  1991-01-13  |  35KB  |  1,290 lines

  1. /*
  2.  *   This program converts AFM files to TeX TFM files, and optionally
  3.  *   to TeX VPL files that retain all kerning and ligature information.
  4.  *   Both files make the characters not normally encoded by TeX available
  5.  *   by character codes greater than 127.
  6.  */
  7.  
  8. /*   (Modified by Don Knuth from Tom Rokicki's pre-VPL version.) */
  9.  
  10. #include <stdio.h>
  11. #ifdef SYSV
  12. #include <string.h>
  13. #else
  14. #ifdef VMS
  15. #include <string.h>
  16. #else
  17. #include <strings.h>
  18. #endif
  19. #endif
  20. #include <math.h>
  21.  
  22. #ifdef MSDOS
  23. #define WRITEBIN "wb"
  24. #else
  25. #define WRITEBIN "w"
  26. #endif
  27.  
  28. char *texencoding[] = {
  29.    "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma",
  30.    "Upsilon", "Phi", "Psi", "Omega", "arrowup", "arrowdown", "quotesingle",
  31.    "exclamdown", "questiondown", "dotlessi", "dotlessj", "grave", "acute",
  32.    "caron", "breve", "macron", "ring", "cedilla", "germandbls", "ae", "oe",
  33.    "oslash", "AE", "OE", "Oslash", "space", "exclam", "quotedbl", "numbersign",
  34.    "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright",
  35.    "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one",
  36.    "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon",
  37.    "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C",
  38.    "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
  39.    "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash",
  40.    "bracketright", "circumflex", "underscore", "quoteleft", "a", "b", "c", "d",
  41.    "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
  42.    "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
  43.    "tilde", "dieresis" } ;
  44. /*
  45.  *   The above layout corresponds to TeX Typewriter Type and is compatible
  46.  *   with TeX Text because the position of ligatures is immaterial.
  47.  */
  48.  
  49. /*
  50.  *   This is what we store Adobe data in.
  51.  */
  52. struct adobeinfo {
  53.    struct adobeinfo *next ;
  54.    int adobenum, texnum, width ;
  55.    char *adobename ;
  56.    int llx, lly, urx, ury ;
  57.    struct lig *ligs ;
  58.    struct kern *kerns ;
  59.    struct pcc *pccs ;
  60.    int wptr, hptr, dptr, iptr ;
  61. } *adobechars, *adobeptrs[256], *texptrs[256],
  62.   *uppercase[256], *lowercase[256] ;
  63. struct lig {
  64.    struct lig *next ;
  65.    char *succ, *sub ;
  66. } ;
  67. struct kern {
  68.    struct kern *next ;
  69.    char *succ ;
  70.    int delta ;
  71. } ;
  72. struct pcc {
  73.    struct pcc *next ;
  74.    char * partname ;
  75.    int xoffset, yoffset ;
  76. } ;
  77.  
  78. FILE *afmin, *vplout, *tfmout ;
  79. char inname[200], outname[200] ; /* names of input and output files */
  80. char buffer[255]; /* input buffer (modified while parsing) */
  81. char obuffer[255] ; /* unmodified copy of input buffer */
  82. char *param ; /* current position in input buffer */
  83. char *fontname = "Unknown" ;
  84. char *codingscheme = "Unspecified" ;
  85. float italicangle = 0.0 ;
  86. char fixedpitch ;
  87. char makevpl ;
  88. int xheight = 400 ;
  89. int fontspace ;
  90. int bc, ec ;
  91. long cksum ;
  92. float efactor = 1.0, slant = 0.0 ;
  93. double newslant ;
  94. char titlebuf[100] ;
  95.  
  96. void
  97. error(s)
  98. register char *s ;
  99. {
  100.    extern void exit() ;
  101.  
  102.    (void)fprintf(stderr, "%s\n", s) ;
  103.    if (obuffer[0]) {
  104.       (void)fprintf(stderr, "%s\n", obuffer) ;
  105.       while (param > buffer) {
  106.          (void)fprintf(stderr, " ") ;
  107.          param-- ;
  108.       }
  109.       (void)fprintf(stderr, "^\n") ;
  110.    }
  111.    if (*s == '!')
  112.       exit(1) ;
  113. }
  114.  
  115. int
  116. transform(x,y)
  117.    register int x,y ;
  118. {
  119.    register double acc ;
  120.    acc = efactor * x + slant *y ;
  121.    return (int)(acc>=0? acc+0.5 : acc-0.5 ) ;
  122. }
  123.  
  124. int
  125. getline() {
  126.    register char *p ;
  127.    register int c ;
  128.  
  129.    param = buffer ;
  130.    for (p=buffer; (c=getc(afmin)) != EOF && c != 10;)
  131.       *p++ = c ;
  132.    *p = 0 ;
  133.    (void)strcpy(obuffer, buffer) ;
  134.    if (p == buffer && c == EOF)
  135.       return(0) ;
  136.    else
  137.       return(1) ;
  138. }
  139.  
  140. char *interesting[] = { "FontName", "ItalicAngle", "IsFixedPitch",
  141.    "XHeight", "C", "KPX", "CC", "EncodingScheme", NULL} ; 
  142. #define FontName (0)
  143. #define ItalicAngle (1)
  144. #define IsFixedPitch (2)
  145. #define XHeight (3)
  146. #define C (4)
  147. #define KPX (5)
  148. #define CC (6)
  149. #define EncodingScheme (7)
  150. #define NONE (-1)
  151. int
  152. interest(s)
  153. char *s ;
  154. {
  155.    register char **p ;
  156.    register int n ;
  157.  
  158.    for (p=interesting, n=0; *p; p++, n++)
  159.       if (strcmp(s, *p)==0)
  160.          return(n) ;
  161.    return(NONE) ;
  162. }
  163.  
  164. char *
  165. mymalloc(len)
  166. int len ;
  167. {
  168.    register char *p ;
  169.    extern char *malloc() ;
  170.  
  171.    p = malloc((unsigned)len) ;
  172.    if (p==NULL)
  173.       error("! out of memory") ;
  174.    return(p) ;
  175. }
  176.  
  177. char *
  178. paramnewstring() {
  179.    register char *p, *q ;
  180.  
  181.    p = param ;
  182.    while (*p > ' ')
  183.       p++ ;
  184.    q = mymalloc((int)(p-param+1)) ;
  185.    if (*p != 0)
  186.       *p++ = 0 ;
  187.    (void)strcpy(q, param) ;
  188.    while (*p && *p <= ' ')
  189.       p++ ;
  190.    param = p ;
  191.    return(q) ;
  192. }
  193.  
  194. char *
  195. paramstring() {
  196.    register char *p, *q ;
  197.  
  198.    p = param ;
  199.    while (*p > ' ')
  200.       p++ ;
  201.    q = param ;
  202.    if (*p != 0)
  203.       *p++ = 0 ;
  204.    while (*p && *p <= ' ')
  205.       p++ ;
  206.    param = p ;
  207.    return(q) ;
  208. }
  209.  
  210. int
  211. paramnum() {
  212.    register char *p ;
  213.    int i ;
  214.  
  215.    p = paramstring() ;
  216.    if (sscanf(p, "%d", &i) != 1)
  217.       error("! integer expected") ;
  218.    return(i) ;
  219. }
  220.  
  221. float
  222. paramfloat() {
  223.    register char *p ;
  224.    float i ;
  225.  
  226.    p = paramstring() ;
  227.    if (sscanf(p, "%f", &i) != 1)
  228.       error("! number expected") ;
  229.    return(i) ;
  230. }
  231.  
  232. struct adobeinfo *
  233. newchar() {
  234.    register struct adobeinfo *ai ;
  235.  
  236.    ai = (struct adobeinfo *)mymalloc(sizeof(struct adobeinfo)) ;
  237.    ai->adobenum = -1 ;
  238.    ai->texnum = -1 ;
  239.    ai->width = -1 ;
  240.    ai->adobename = NULL ;
  241.    ai->llx = -1 ;
  242.    ai->lly = -1 ;
  243.    ai->urx = -1 ;
  244.    ai->ury = -1 ;
  245.    ai->ligs = NULL ;
  246.    ai->kerns = NULL ;
  247.    ai->pccs = NULL ;
  248.    ai->next = adobechars ;
  249.    adobechars = ai ;
  250.    return(ai) ;
  251. }
  252.  
  253. struct kern *
  254. newkern() {
  255.    register struct kern *nk ;
  256.  
  257.    nk = (struct kern *)mymalloc(sizeof(struct kern)) ;
  258.    nk->next = NULL ;
  259.    nk->succ = NULL ;
  260.    nk->delta = 0 ;
  261.    return(nk) ;
  262. }
  263.  
  264. struct pcc *
  265. newpcc() {
  266.    register struct pcc *np ;
  267.  
  268.    np = (struct pcc *)mymalloc(sizeof(struct pcc)) ;
  269.    np->next = NULL ;
  270.    np->partname = NULL ;
  271.    np->xoffset = 0 ;
  272.    np->yoffset = 0 ;
  273.    return(np) ;
  274. }
  275.  
  276. struct lig *
  277. newlig() {
  278.    register struct lig *nl ;
  279.  
  280.    nl = (struct lig *)mymalloc(sizeof(struct lig)) ;
  281.    nl->next = NULL ;
  282.    nl->succ = NULL ;
  283.    nl->sub = NULL ;
  284.    return(nl) ;
  285. }
  286.  
  287. void
  288. expect(s)
  289. char *s ;
  290. {
  291.    if (strcmp(paramstring(), s) != 0) {
  292.       (void)fprintf(stderr, "%s expected: ", s) ;
  293.       error("! syntax error") ;
  294.    }
  295. }
  296.  
  297. void
  298. handlechar() { /* an input line beginning with C */
  299.    register struct adobeinfo *ai ;
  300.    register struct lig *nl ;
  301.  
  302.    ai = newchar() ;
  303.    ai->adobenum = paramnum() ;
  304.    expect(";") ;
  305.    expect("WX") ;
  306.    ai->width = transform(paramnum(),0) ;
  307.    if (ai->adobenum >= 0 && ai->adobenum < 256) {
  308.       adobeptrs[ai->adobenum] = ai ;
  309.       cksum = (cksum<<1) ^ ai->width ;
  310.    }
  311.    expect(";") ;
  312.    expect("N") ;
  313.    ai->adobename = paramnewstring() ;
  314.    expect(";") ;
  315.    expect("B") ;
  316.    ai->llx = paramnum() ;
  317.    ai->lly = paramnum() ;
  318.    ai->llx = transform(ai->llx, ai->lly) ;
  319.    ai->urx = paramnum() ;
  320.    ai->ury = paramnum() ;
  321.    ai->urx = transform(ai->urx, ai->ury) ;
  322. /* We need to avoid negative heights or depths. They break accents in
  323.    math mode, among other things.  */
  324.    if (ai->lly > 0)
  325.       ai->lly = 0 ;
  326.    if (ai->ury < 0)
  327.       ai->ury = 0 ;
  328.    expect(";") ;
  329. /* Now look for ligatures (which aren't present in fixedpitch fonts) */
  330.    while (*param == 'L') {
  331.       expect("L") ;
  332.       nl = newlig() ;
  333.       nl->succ = paramnewstring() ;
  334.       nl->sub = paramnewstring() ;
  335.       nl->next = ai->ligs ;
  336.       ai->ligs = nl ;
  337.       expect(";") ;
  338.    }
  339.    if (strcmp(ai->adobename, "space")==0) {
  340.       fontspace = ai->width ;
  341.       nl = newlig() ;        /* space will act as zero-width Polish crossbar */
  342.       nl->succ = "l" ;       /* when used by plain TeX's \l or \L macros */
  343.       nl->sub = "lslash" ;
  344.       nl->next = ai->ligs ;
  345.       ai->ligs = nl ;
  346.       nl = newlig() ;
  347.       nl->succ = "L" ;
  348.       nl->sub = "Lslash" ;
  349.       nl->next = ai->ligs ;
  350.       ai->ligs = nl ;
  351.    } else if (strcmp(ai->adobename, "question")==0) {
  352.       nl = newlig() ;
  353.       nl->succ = "quoteleft" ;
  354.       nl->sub = "questiondown" ;
  355.       nl->next = ai->ligs ;
  356.       ai->ligs = nl ;
  357.    } else if (strcmp(ai->adobename, "exclam")==